#include "tcpServer.hpp"

#include <iostream>
#include <memory>

using namespace std;
using namespace tcpserver;


bool cal(Request &req, Response &resp) // 服务器要执行的业务逻辑方法
{
    // req已经有反序列化之后的数据了，可以直接使用
    // 先把resp的所有字段初始化为0
    resp._exitcode = OK;
    resp._result = OK;
    // logMessage(DEBUG, "%d %c %d", req._x, req._y, req._op);

    switch (req._op)
    {
    case '+':
        resp._result = req._x + req._y;
        break;
    case '-':
        resp._result = req._x - req._y;
        break;
    case '*':
        resp._result = req._x * req._y;
        break;
    case '/':
    {
        if (req._y == 0)
            resp._exitcode = DIV_ZERO;
        else
            resp._result = req._x / req._y;
    }
    break;
    case '%':
    {
        if (req._y == 0)
            resp._exitcode = MOD_ZERO;
        else
            resp._result = req._x % req._y;
    }
    break;
    default:
        resp._exitcode = OP_ERROR;
        break;
    }
    logMessage(DEBUG, "result: %d, exitcode: %d", resp._result, resp._exitcode);

    return true;
}
// 到这里，已经把本轮就绪的fd事件中的接收缓冲区中的数据全部拿到sock的inbuffer里面了，下面要做的就是解析出一个完整的报文
void calculate(Connection *conn)
{
    string onePackage;
    while (ParseOnePackage(conn->_inbuffer, &onePackage)) // 有可能对方发送过来的字节流可以解析出很多的报文
    {
        logMessage(DEBUG, "while in");
        string req_str;
        if (!deLength(onePackage, &req_str))
            return;
        logMessage(DEBUG, "req_str: %s", req_str.c_str());

        cout << "去掉报头的正文请求: \n"
             << req_str << endl;

        // 2. 将读到的报文(请求)先进行反序列化
        // 2.1 通过反序列化, 得到一个结构化的请求对象req
        Request req;
        if (!req.deserialize(req_str))
            return;

        Response resp;
        cal(req, resp);

        // 4. 对结构化的响应进行序列化
        // 4.1 得到了一个序列化后的"字符串"
        string resp_str;
        resp.serialize(&resp_str);

        // 5. 将序列化后的报文(响应)发送给客户端
        // 5.1 将序列化后的响应构建成为一个完整的报文
        conn->_outbuffer += enLength(resp_str);

        // 把序列化后的完整应用层响应报文发回去
        // logMessage(DEBUG, "Server handle result: %s", send_string.c_str());
    }
    // 把收到的所有字节流构建出响应发回去，如果写事件没有就绪，则send返回的errno为EAGAIN，send循环就会退出
    if (conn->_sender)
        conn->_sender(conn);
}
void Usage(char *proc)
{
    cout << "Usage: \n\t" << proc << "port"
         << "\n\n";
    exit(USAGE_ERR);
}
//./epoll_server port
int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    unique_ptr<TcpServer> tsvr(new TcpServer(calculate, port));
    tsvr->initServer();
    tsvr->Dispatcher(); // 事件派发

    return 0;
}